home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 1 / Mac Magazin and MacEasy Magazine CD - Issue 01.iso / Sharewarebibliothek / Powermac / C64 / SOURCE / ColorVIC.c < prev    next >
Text File  |  1994-06-06  |  14KB  |  554 lines

  1. /*
  2.     Commodore 64 Emulator v0.4        Earle F. Philhower III 
  3.     Copyright (C) 1993-4            (st916w9r@dunx1.ocs.drexel.edu)
  4.  
  5.     This program is    free software; you can redistribute    it and/or modify
  6.     it under the terms of the GNU General Public License as    published by
  7.     the    Free Software Foundation; either version 2 of the License, or
  8.     (at    your option) any later version.
  9.  
  10.     This program is    distributed    in the hope    that it    will be    useful,
  11.     but    WITHOUT    ANY    WARRANTY; without even the implied warranty    of
  12.     MERCHANTABILITY    or FITNESS FOR A PARTICULAR    PURPOSE.  See the
  13.     GNU    General    Public License for more    details.
  14.  
  15.     You    should have    received a copy    of the GNU General Public License
  16.     along with this    program; if    not, write to the Free Software
  17.     Foundation,    Inc., 675 Mass Ave,    Cambridge, MA 02139, USA.
  18. */
  19. #include "Processor.h"
  20. #include "Memory.h"
  21. #include "Error.h"
  22. #include "Resources.h"
  23. #include "VIC.h"
  24. #include <QDOffscreen.h>
  25. #include <GestaltEqu.h>
  26.  
  27. void TotalRedrawVIC(void);
  28. void SetupColorTable(void);
  29. OSErr CreateGDevice (PixMapHandle, GDHandle*);
  30. void NewBitMap (PixMapHandle, Rect*);
  31. OSErr CreateOffScreen (Rect*, short, CTabHandle, CGrafPtr*, GDHandle*);
  32. OSErr SetUpPixMap(short, Rect*, CTabHandle, short, PixMapHandle);
  33.  
  34. /*
  35.    kPixDepth is the pixel depth of the offscreen pixmap,
  36.    kClutID is the resID of the color table,
  37.    and kDefaultRes has to do with the screen resolution of the GDevice
  38. */
  39.  
  40. #define    kPixDepth    8
  41. #define    kClutID        1001
  42. #define kDefaultRes 0x00480000
  43.  
  44.  
  45. static Rect leftRect, rightRect, topRect, botRect, spr, screenRect;
  46. static PixMapHandle spriteMapH;
  47. static CTabHandle VICTab;
  48. static GDHandle offDev;
  49. static RGBColor VICcolors[16], back0Col, frontCol, back1Col, back2Col;
  50. static CGrafPtr offScreenPtr;
  51. static CGrafPtr spriteGraf;    /* not used yet */
  52. static byte VICColor[1024];
  53.  
  54. extern Rect colorWindRect, colorFullRect;
  55.  
  56. int ColorVICInitialize()
  57. {
  58.     short err;
  59.     CTabHandle vicColors;
  60.     long gestRet;
  61.  
  62.     Gestalt(gestaltQuickdrawVersion, &gestRet);
  63.     if (gestRet<gestalt8BitQD) return kNoColorSupport;
  64.  
  65.     SetRect(&colorFullRect,0,0,336,210);
  66.     SetRect(&screenRect,8,5,328,205);
  67.     SetRect(&leftRect,0,0,8,210);
  68.     SetRect(&rightRect,328,0,336,210);
  69.     SetRect(&topRect,0,0,336,5);
  70.     SetRect(&botRect,0,205,336,210);
  71.     SetRect(&spr,0,0,24,21);
  72.     SetupColorTable();
  73.     ColorVICWind = (CWindowPtr)GetNewCWindow (kColorVIC, nil, (WindowPtr)-1L);
  74.     if (ColorVICWind==nil) return (kMissingResource);
  75.     vicColors = VICTab;
  76.     err = HandToHand((Handle*)&vicColors);
  77.     (**(ColorVICWind->portPixMap)).pixelType = 0;
  78.     (**(ColorVICWind->portPixMap)).cmpCount = 1;
  79.     (**(ColorVICWind->portPixMap)).cmpSize = kPixDepth;
  80.     (**(ColorVICWind->portPixMap)).pmTable = vicColors;
  81.     DisposCTable(vicColors);
  82.     spriteMapH = NewPixMap();
  83.     SetUpPixMap(kPixDepth, &spr, VICTab, kPixDepth*(spr.right-spr.left), spriteMapH);
  84.     CreateOffScreen (&colorFullRect, kPixDepth, VICTab, &offScreenPtr, &offDev);
  85.  
  86.     return(kNoError);
  87. }
  88.  
  89. void ShowColorVIC()
  90. {
  91.     ShowWindow((WindowPtr)ColorVICWind);
  92.     SetPort((GrafPtr)ColorVICWind);
  93.     SelectWindow((WindowPtr)ColorVICWind);
  94. }
  95.  
  96. void HideColorVIC()
  97. {
  98.     HideWindow((WindowPtr)ColorVICWind);
  99. }
  100.  
  101. static void DrawSprites()
  102. {
  103.     byte spriteNum, row, *spb0, *spb1, *spb2;
  104.     word xpos, ypos, addr0, addr1, addr2;
  105.     Rect t;
  106.     
  107. /*    BlockMove((**VICMapH).baseAddr, (**fullMapH).baseAddr,
  108.                 GetPtrSize((**VICMapH).baseAddr));
  109. */
  110.     SetPortPix (spriteMapH);
  111.     for (spriteNum=0; spriteNum<8; spriteNum++)
  112.         if (VICRegister[0x15]&(1<<spriteNum)) {
  113.             xpos=VICRegister[0x00+spriteNum*2]-24;
  114.             ypos=VICRegister[0x01+spriteNum*2]-50;
  115.             xpos += (VICRegister[0x10]&(1<<spriteNum))?256:0;
  116.             t.top=ypos;t.left=xpos;
  117.             t.right=t.left+24+((VICRegister[0x1d]&(1<<spriteNum))?24:0);
  118.             t.bottom=t.top+21+((VICRegister[0x17]&(1<<spriteNum))?21:0);
  119.             addr0 = VICAddrBase+RAM[VICScreenPage+1016+spriteNum]*64;
  120.             addr1 = addr0+1;
  121.             addr2 = addr1+1;
  122.             spb0 = (byte*) ((**spriteMapH).baseAddr);
  123.             spb1 = spb0+1;
  124.             spb2 = spb0+2;
  125.             for (row=0; row<21; row++) {
  126.                 spb0[row<<2]=RAM[addr0+row*3];
  127.                 spb1[row<<2]=RAM[addr1+row*3];
  128.                 spb2[row<<2]=RAM[addr2+row*3]; }
  129.             CopyBits((BitMap*)*spriteMapH,(BitMap*)(*(offScreenPtr->portPixMap)),&spr,&t,srcOr,nil); }
  130.     SetPortPix (offScreenPtr->portPixMap);
  131. }
  132.  
  133. void FastDraw(byte row, byte col, word chr)
  134. {    
  135.     register short tempa, tempb, pos, h;
  136.     short line;
  137.     
  138.     tempa=(row<<3)+screenRect.top; tempb=chr<<3;
  139.     Index2Color(RAM[55296+chr],&frontCol);
  140.     RGBForeColor(&frontCol);
  141.     for    (line=0;line<8;line++)
  142.         for    (h=(col<<3)+screenRect.left,pos=0x80;pos>0;pos>>=1,++h)
  143.             if (*(VICCharDefs+tempb+line)&pos) {
  144.                 MoveTo(h,line+tempa);
  145.                 Line(0,0);
  146.             }
  147. }
  148.  
  149. void MultiDraw(byte row, byte col, word chr)
  150. {    
  151.     short tempa, tempb, line, shift, pos, h;
  152.     tempa=(row<<3)+screenRect.top; tempb=chr<<3;
  153.     Index2Color(RAM[55296+chr],&frontCol);
  154.     for    (line=0;line<8;line++)
  155.         for    (h=(col<<3)+screenRect.left,pos=0xC0,shift=6;pos>0;pos>>=2,h+=2,shift-=2) {
  156.             switch ((*(VICCharDefs+tempb+line)&pos)>>shift) {
  157.                 case 0: RGBForeColor(&back0Col); break;
  158.                 case 1: RGBForeColor(&back1Col); break;
  159.                 case 2: RGBForeColor(&back2Col); break;
  160.                 case 3: RGBForeColor(&frontCol); break;
  161.             }
  162.             MoveTo(h,line+tempa);
  163.             Line(1,0);
  164.         }
  165. }
  166.  
  167. void DrawTextScreen(byte total)
  168. {
  169.     word chr;
  170.     byte row, col;
  171.     GrafPtr    savePort;
  172.     GDHandle saveDev;
  173.     Rect back;
  174.     byte* colorBase;
  175.     byte multiColor;
  176.     
  177.     row=col=0;
  178.     colorBase =    &RAM[55296];
  179.     GetPort    (&savePort);
  180.     saveDev    = GetGDevice();
  181.     SetPort    ((GrafPtr)offScreenPtr);
  182.     SetGDevice (offDev);
  183.     PenSize(1,1);
  184.     multiColor = (VICRegister[0x16]&16);
  185.     Index2Color    (VICRegister[0x21],    &back0Col);
  186.     Index2Color (VICRegister[0x22], &back1Col);
  187.     Index2Color (VICRegister[0x23], &back2Col);
  188.     RGBBackColor (&back0Col);
  189. /*    SetOrigin(-(VICRegister[0x16]&7),-((VICRegister[0x11]&7)-3));*/
  190.     if (VICRegister[0x11]&32)     /*     High Res mode    */
  191.     {
  192.         VICCharDefs=RAM+VICAddrBase+((VICRegister[0x18]&8)?8192:0);
  193.         for    (chr=0;chr<1000;chr++) {
  194.             FastDraw(row,col,chr);
  195.             if (++col>39) {col=0;row++;} }
  196.         }
  197.     else if    (total)     {
  198.             EraseRect (&screenRect);
  199.             for    (chr=0;chr<1000;chr++) {
  200.                 if (multiColor && (RAM[55296+chr]>=8)) MultiDraw(row,col,RAM[chr+VICScreenPage]);
  201.                 else FastDraw(row,col,RAM[chr+VICScreenPage]);
  202.                 VICText[chr]=RAM[chr+VICScreenPage];
  203.                 VICColor[chr]=RAM[55296+chr];
  204.                 if (++col>39) {col=0;row++;} } }
  205.     else  {
  206.             for    (chr=0;chr<1000;chr++) {
  207.                 if ((VICText[chr]!=RAM[chr+VICScreenPage])||(VICColor[chr]!=RAM[55296+chr])) {
  208.                     SetRect    (&back,    (col<<3)+screenRect.left, (row<<3)+screenRect.top,
  209.                                     (col<<3)+screenRect.left+8,    (row<<3)+screenRect.top+8);
  210.                     EraseRect (&back);
  211.                     if (multiColor && (RAM[55296+chr]>=8)) MultiDraw(row,col,RAM[chr+VICScreenPage]);
  212.                     else FastDraw(row,col,RAM[chr+VICScreenPage]);
  213.                     VICColor[chr]=RAM[55296+chr];
  214.                     VICText[chr]=RAM[chr+VICScreenPage]; }
  215.                 if (++col>39) {col=0;row++;} } }
  216. /*    SetOrigin(0,0);*/
  217.     SetPort    (savePort);
  218.     SetGDevice (saveDev);
  219. /*    ScrollRect(&colorFullRect, VICRegister[0x16]&7,(VICRegister[0x11]&7)-3,nil);*/
  220. }
  221.  
  222.  
  223. static void DrawBorders()
  224. {
  225.     GrafPtr savePort;
  226.     GDHandle saveDev;
  227.     RGBColor borderCol;
  228.     Rect newLeft, newRight, newTop, newBottom;
  229.  
  230.     GetPort (&savePort);
  231.     saveDev = GetGDevice();
  232.     SetPort ((GrafPtr)offScreenPtr);
  233.     SetGDevice (offDev);
  234.     Index2Color (VICRegister[0x20], &borderCol);
  235.     RGBBackColor (&borderCol);
  236.     if (VICRegister[0x16]&8) {
  237.         EraseRect(&leftRect);
  238.         EraseRect(&rightRect);
  239.     }
  240.     else {
  241.         newLeft = leftRect;
  242.         OffsetRect (&newLeft, 4, 0);
  243.         InsetRect (&newLeft, -4, 0);
  244.         newRight = rightRect;
  245.         OffsetRect (&newRight, -4, 0);
  246.         InsetRect (&newRight, -4, 0);
  247.         EraseRect(&newLeft);
  248.         EraseRect(&newRight);
  249.     }
  250.     if (VICRegister[0x11]&8) {
  251.         EraseRect(&botRect);
  252.         EraseRect(&topRect);
  253.     }
  254.     else {
  255.         newBottom = botRect;
  256.         OffsetRect (&newBottom, 0, -2);
  257.         InsetRect (&newBottom, 0, -2);
  258.         newTop = topRect;
  259.         OffsetRect (&newTop, 0, 2);
  260.         InsetRect (&newTop, 0, -2);
  261.         EraseRect(&newBottom);
  262.         EraseRect(&newTop);
  263.     }
  264.     SetPort (savePort);
  265.     SetGDevice (saveDev);
  266. }
  267.  
  268. static void CopyPortToScreen()
  269. {
  270.     ForeColor (blackColor);
  271.     BackColor (whiteColor);
  272.     CopyBits ((BitMapPtr)*(offScreenPtr->portPixMap), &((GrafPtr)ColorVICWind)->portBits, &colorFullRect, &colorWindRect, srcCopy, nil);
  273. }
  274.  
  275. static void BlankScreen()
  276. {
  277.     GrafPtr savePort;
  278.     GDHandle saveDev;
  279.     RGBColor backCol;
  280.  
  281.     GetPort (&savePort);
  282.     saveDev = GetGDevice();
  283.     SetPort ((GrafPtr)offScreenPtr);
  284.     SetGDevice (offDev);
  285.     Index2Color (VICRegister[0x21], &backCol);
  286.     RGBBackColor (&backCol);
  287.     EraseRect (&colorFullRect);
  288.     SetPort (savePort);
  289.     SetGDevice (saveDev);
  290.     CopyPortToScreen();
  291.     return;
  292. }
  293.  
  294. void ColorRedrawVIC()
  295. {
  296.     SetPort((GrafPtr)ColorVICWind);
  297.     if (!VICRegister[0x11]&16) {
  298.         BlankScreen(); 
  299.         return;}
  300.     DrawTextScreen(0);
  301.     DrawBorders();
  302.     if (VICRegister[0x15])
  303.         DrawSprites();
  304.     CopyPortToScreen();
  305. }
  306.  
  307. void ColorTotalRedrawVIC()
  308. {
  309.     SetPort((GrafPtr)ColorVICWind);    
  310.     if (VICRegister[0x11]&16)            /* screen blanking */
  311.         ;
  312.     else 
  313.     {
  314.         BlankScreen();
  315.         return;
  316.     }
  317.     DrawBorders();
  318.     DrawTextScreen(1);
  319.     if (VICRegister[0x15])
  320.         DrawSprites();
  321.     CopyPortToScreen();
  322. }
  323.  
  324. void SetupColorTable (void)
  325. {
  326.     VICTab = GetCTable (kClutID);
  327.     HNoPurge ((Handle)VICTab);
  328.     MoveHHi ((Handle)VICTab);
  329. }
  330.  
  331. /*
  332.    These next three are almost verbatim from the Tech Note "Principia Off Screen"
  333. */
  334.  
  335. OSErr CreateGDevice (PixMapHandle basePixMap, GDHandle *retGDevice)
  336. {
  337.     GDHandle   newDevice;
  338.     ITabHandle embryoITab;
  339.     Rect       deviceRect;
  340.     OSErr       error;
  341.  
  342.     error =    noErr;
  343.     newDevice =    nil;
  344.     embryoITab = nil;
  345.  
  346.     newDevice = (GDHandle)NewHandle(sizeof(GDevice));
  347.     if (newDevice != nil)
  348.     {
  349.         embryoITab = (ITabHandle)NewHandleClear(2);
  350.         if (embryoITab != nil)
  351.         {
  352.             deviceRect = (**basePixMap).bounds;
  353.             (**newDevice).gdRefNum = 0;
  354.             (**newDevice).gdID = 0;
  355.             if ((**basePixMap).pixelSize <=    8)
  356.                 (**newDevice).gdType = clutType;
  357.             else
  358.                 (**newDevice).gdType = directType;
  359.             (**newDevice).gdITable = embryoITab;
  360.             (**newDevice).gdResPref    = 4;
  361.             (**newDevice).gdSearchProc = nil;
  362.             (**newDevice).gdCompProc = nil;
  363.             (**newDevice).gdFlags =    0;
  364.             (**newDevice).gdPMap = basePixMap;
  365.             (**newDevice).gdRefCon = 0;
  366.             (**newDevice).gdNextGD = nil;
  367.             (**newDevice).gdRect = deviceRect;
  368.             (**newDevice).gdMode = -1;
  369.             (**newDevice).gdCCBytes    = 0;
  370.             (**newDevice).gdCCDepth    = 0;
  371.             (**newDevice).gdCCXData    = 0;
  372.             (**newDevice).gdCCXMask    = 0;
  373.             (**newDevice).gdReserved = 0;
  374.             if ((**basePixMap).pixelSize > 1)
  375.                 SetDeviceAttribute(    newDevice, gdDevType, true );
  376.             SetDeviceAttribute(    newDevice, noDriver, true );
  377.             if ((**basePixMap).pixelSize <=    8)
  378.             {
  379.                 MakeITable((**basePixMap).pmTable, (**newDevice).gdITable,(**newDevice).gdResPref);
  380.                 error =    QDError();
  381.             }
  382.         }
  383.         else
  384.             error =    MemError();
  385.     }
  386.     else
  387.         error =    MemError();
  388.     if (error != noErr)
  389.     {
  390.         if (embryoITab != nil)
  391.             DisposHandle( (Handle)embryoITab );
  392.         if (newDevice != nil)
  393.             DisposHandle( (Handle)newDevice    );
  394.     }
  395.     else
  396.         *retGDevice    = newDevice;
  397.     return error;
  398. }
  399.  
  400. OSErr CreateOffScreen (Rect *bounds, short depth, CTabHandle colors, CGrafPtr *retPort,    GDHandle *retGDevice)
  401. {
  402.     CGrafPtr    newPort;
  403.     PixMapHandle    newPixMap;
  404.     GDHandle    newDevice;
  405.     long        qdVersion;
  406.     GrafPtr        savedPort;
  407.     SignedByte    savedState;
  408.     short        bytesPerRow;
  409.     OSErr        error;
  410.  
  411.     newPort    = nil;
  412.     newPixMap = nil;
  413.     newDevice = nil;
  414.     error =    noErr;
  415.     if (colors != nil)
  416.     {
  417.         savedState = HGetState(    (Handle)colors );
  418.         HNoPurge( (Handle)colors );
  419.     }
  420.     bytesPerRow    = ((depth *    (bounds->right - bounds->left) + 31) >>    5) << 2;
  421.     (void)Gestalt( gestaltQuickdrawVersion,    &qdVersion );
  422.     if (depth == 1 || depth    == 2 ||    depth == 4 || depth    == 8 ||
  423.             ((depth    == 16 || depth == 32) && qdVersion >= gestalt32BitQD))
  424.     {
  425.         if (bytesPerRow    <= 0x3FFE)
  426.         {
  427.             if (depth <= 8)
  428.                 if (colors == nil)
  429.                   error    = paramErr;    /* no table for indexed depth */
  430.         }
  431.         else
  432.             error =    paramErr; /* too many bytes */
  433.     }
  434.     else
  435.         error =    paramErr; /* invalid depth */
  436.     if (error == noErr)
  437.     {
  438.         newPort    = (CGrafPtr)NewPtr(    sizeof (CGrafPort) );
  439.         if (newPort    != nil)
  440.         {
  441.             GetPort    (&savedPort);
  442.             OpenCPort (newPort);
  443.             newPort->portRect =    *bounds;
  444.             RectRgn    (newPort->visRgn, bounds);
  445.             ClipRect (bounds);
  446.             error =    SetUpPixMap    (depth,    bounds,    colors,    bytesPerRow, newPort->portPixMap);
  447.             if (error == noErr)
  448.             {
  449.                 newPixMap =    newPort->portPixMap;
  450.                 error =    CreateGDevice( newPixMap, &newDevice );
  451.             }
  452.             SetPort( savedPort );
  453.         }
  454.         else
  455.             error =    MemError();
  456.     }
  457.     if (colors != nil)
  458.         HSetState( (Handle)colors, savedState );
  459.     if (error != noErr)
  460.     {
  461.         if (newPixMap != nil)
  462.         {
  463.             DisposCTable( (**newPixMap).pmTable    );
  464.             DisposPtr( (**newPixMap).baseAddr );
  465.         }
  466.         if (newDevice != nil)
  467.         {
  468.             DisposHandle( (Handle)(**newDevice).gdITable );
  469.             DisposHandle( (Handle)newDevice    );
  470.         }
  471.         if (newPort    != nil)
  472.         {
  473.             CloseCPort(    newPort    );
  474.             DisposPtr( (Ptr)newPort    );
  475.         }
  476.     }
  477.     else
  478.     {
  479.         *retPort = newPort;
  480.         *retGDevice    = newDevice;
  481.     }
  482.     return error;
  483. }
  484.  
  485. OSErr SetUpPixMap(short    depth, Rect    *bounds, CTabHandle    colors,    short bytesPerRow, PixMapHandle    aPixMap)
  486. {
  487.     CTabHandle newColors;
  488.     Ptr           offBaseAddr;
  489.     OSErr       error;
  490.  
  491.     error =    noErr;
  492.     newColors =    nil;
  493.     offBaseAddr    = nil;
  494.     if (depth <= 8)
  495.     {
  496.         newColors =    colors;
  497.         error =    HandToHand(    (Handle    *)&newColors );
  498.     }
  499.     else
  500.     {
  501.         newColors =    (CTabHandle)NewHandle(sizeof(ColorTable) - sizeof(CSpecArray));
  502.         error =    MemError();
  503.     }
  504.     if (error == noErr)
  505.     {
  506.         offBaseAddr    = NewPtr((unsigned long)bytesPerRow    * (bounds->bottom -    bounds->top) );
  507.         if (offBaseAddr    != nil)
  508.         {
  509.             (**aPixMap).baseAddr = offBaseAddr;
  510.             (**aPixMap).rowBytes = bytesPerRow | 0x8000;
  511.             (**aPixMap).bounds = *bounds;
  512.             (**aPixMap).pmVersion =    0;
  513.             (**aPixMap).packType = 0;
  514.             (**aPixMap).packSize = 0;
  515.             (**aPixMap).hRes = kDefaultRes;
  516.             (**aPixMap).vRes = kDefaultRes;
  517.             (**aPixMap).pixelSize =    depth;
  518.             (**aPixMap).planeBytes = 0;
  519.             (**aPixMap).pmReserved = 0;
  520.             if (depth <= 8)      /* PixMap    is indexed */
  521.             {
  522.                 (**aPixMap).pixelType =    0;
  523.                 (**aPixMap).cmpCount = 1;
  524.                 (**aPixMap).cmpSize    = depth;
  525.                 (**aPixMap).pmTable    = newColors;
  526.             }
  527.             else
  528.             {
  529.                 (**aPixMap).pixelType =    RGBDirect;
  530.                 (**aPixMap).cmpCount = 3;
  531.                 if (depth == 16)
  532.                     (**aPixMap).cmpSize    = 5;
  533.                 else
  534.                     (**aPixMap).cmpSize    = 8;
  535.                 (**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
  536.                 (**newColors).ctFlags =    0;
  537.                 (**newColors).ctSize = 0;
  538.                 (**aPixMap).pmTable    = newColors;
  539.             }
  540.         }
  541.         else
  542.             error =    MemError();
  543.     }
  544.     else
  545.         newColors =    nil;
  546.     if (error != noErr)
  547.     {
  548.         if (newColors != nil)
  549.             DisposCTable(newColors);
  550.     }
  551.     return error;
  552. }
  553.  
  554.